import { forwardRef, useImperativeHandle } from 'react'
import classNames from 'classnames'
import { warn } from '@/library/tool-kits/log'
import { useCheckboxGroup } from './group-context'
import { NativeInput } from './native-input'
import { usePropsValue } from '../../hooks/use-props-value'
import { withNativeProps } from '../../utils/native-props'
import type { CheckboxProps, CheckboxRef } from './type'
import { IndeterminateIcon } from './indeterminate-icon'
import { CheckIcon } from './check-icon'

const classPrefix = 'rt-checkbox'

export const Checkbox = forwardRef<CheckboxRef, CheckboxProps>((props, ref) => {
  const context = useCheckboxGroup()

  const {
    block,
    checked,
    defaultChecked = false,
    id,
    icon,
    indeterminate = false,
    onClick,
    onChange,
    shape = 'default',
    value,
    children,
  } = props

  let { disabled = false } = props

  let [actChecked, setActChecked] = usePropsValue({
    value: checked,
    defaultValue: defaultChecked,
    onChange,
  })

  if (context && value === undefined) {
    warn(
      'Checkbox',
      'When used within `Checkbox.Group`, the `value` prop of `Checkbox` shouldn\'t be Undefined.',
    )
    return null
  }

  if (context && value !== undefined) {
    if (checked !== undefined) {
      warn(
        'Checkbox',
        'When used within `Checkbox.Group`, the `checked` prop of `Checkbox` will not work.',
      )
    }
    if (defaultChecked) {
      warn(
        'Checkbox',
        'When used within `Checkbox.Group`, the `defaultChecked` prop of `Checkbox` will not work.',
      )
    }

    actChecked = context.value.includes(value)

    setActChecked = function (check: boolean) {
      if (check) {
        context.check(value)
      } else {
        context.uncheck(value)
      }
      onChange?.(check)
    } as any

    disabled = disabled || context.disabled
  }

  /**
   * 不适用于 `Group` 模式
   */
  // eslint-disable-next-line react-hooks/rules-of-hooks
  useImperativeHandle(ref, () => ({
    check: () => {
      setActChecked(true)
    },
    uncheck: () => {
      setActChecked(false)
    },
    toggle: () => {
      setActChecked(!actChecked)
    },
    get getCheckState() {
      return actChecked
    },
  }))

  const renderIcon = () => {
    if (icon) {
      return (
        <div className={`${classPrefix}-custom-icon`}>
          {icon(actChecked, indeterminate)}
        </div>
      )
    }

    return (
      <div className={classNames(
        `${classPrefix}-icon`,
        `${classPrefix}-icon-${shape}`,
      )}
      >
        {indeterminate ? <IndeterminateIcon /> : (actChecked && <CheckIcon />)}
      </div>
    )
  }

  return withNativeProps(
    props,
    // eslint-disable-next-line jsx-a11y/label-has-associated-control, jsx-a11y/no-noninteractive-element-interactions
    <label
      onClick={onClick}
      className={classNames(classPrefix, {
        [`${classPrefix}-checked`]: actChecked && !indeterminate,
        [`${classPrefix}-indeterminate`]: indeterminate,
        [`${classPrefix}-disabled`]: disabled,
        [`${classPrefix}-block`]: block,
      })}
    >
      <NativeInput
        type="checkbox"
        checked={actChecked}
        onChange={setActChecked}
        disabled={disabled}
        id={id}
      />
      {renderIcon()}
      {children && (
        <div className={`${classPrefix}-content`}>{children}</div>
      )}
    </label>,
  )
})
